package com.woniu.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.alipay.api.AlipayApiException;
import com.woniu.HisHospitalizationApi.HisHospitalRecordsApi;
import com.woniu.api.*;
import com.woniu.config.AppConfig;
import com.woniu.dto.*;
import com.woniu.exception.DIYException;
import com.woniu.exception.OutpatientException;
import com.woniu.hisoutpatientservicefacade.dto.LoginDto;
import com.woniu.hisoutpatientservicefacade.dto.QueryMedicalRecordParam;
import com.woniu.hisoutpatientservicefacade.dto.ViewInspectionResultsDto;
import com.woniu.hisoutpatientservicefacade.param.*;
import com.woniu.hisoutpatientservicefacade.param.LoginParam;
import com.woniu.param.*;
import com.woniu.service.OutpatientService;
import com.woniu.util.CopyBeanUtil;
import com.woniu.util.Result;
import org.apache.ibatis.annotations.Param;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageDeliveryMode;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class OutpatientServiceImpl implements OutpatientService {

    @Resource
    private RabbitTemplate rabbitTemplate;

    @Resource
    private RedissonClient redissonClient;


    //患者
    @Resource
    private HisPatientQueryApi patientQueryApi;
    @Resource
    private HisRegisterQueryApi registerQueryApi;
    @Resource
    private HisCaseQueryApi caseQueryApi;
    @Resource
    private HisPrescriptionQueryApi prescriptionQueryApi;

    //检查
    @Resource
    private HisCheckPriceAPI checkPriceAPI;
    @Resource
    private HisCheckAPI checkAPI;
    @Resource
    private HisUroscopyAPI uroscopyAPI;
    @Resource
    private HisImageAPI imageAPI;
    @Resource
    private HisBloodAPI bloodAPI;

    //医护
    @Resource
    private HisSchedulingAPI schedulingAPI;
    @Resource
    private HisOfficeAPI officeAPI;
    @Resource
    private HisStaffAPI staffAPI;

    //药房
    @Resource
    private StockApi stockApi;
    @Resource
    private DrugsApi drugsApi;

    //缴费
    @Resource
    private PayApi payApi;

    //住院服务
    @Resource
    private HisHospitalRecordsApi hospitalRecordsApi;

    //挂号前登录
    @Override
    public LoginDto login(LoginParam param) {

        //添加就诊人
        RegistratPatientParam patientParam = new RegistratPatientParam();
        BeanUtils.copyProperties(param, patientParam);
        Result<HisPatientDto> patientDtoResult = patientQueryApi.registrationOperation(patientParam);
        HisPatientDto patientDto = patientDtoResult.getData();

        //获取token
        LoginHisPatientParam loginHisPatientParam = CopyBeanUtil.copyBean(patientDto, LoginHisPatientParam.class);
        Result<HisPatientDto> patientDtoResult2 = patientQueryApi.loginOperation(loginHisPatientParam);
        patientDto.setToken(patientDtoResult2.getData().getToken());

        //查询患者挂号记录
        PastRegistrationParam pastRegistrationParam = new PastRegistrationParam();
        pastRegistrationParam.setPatientId(patientDto.getPatientId());
        Result<PageDTO<HisRegisterDto>> pageDtoResult = registerQueryApi.pastRegistration(pastRegistrationParam);

        LoginDto<HisPatientDto, PageDTO> loginDto = new LoginDto<>();
        loginDto.setPageDto(pageDtoResult.getData());
        loginDto.setPatientDto(patientDto);

        return loginDto;
    }

    //查询所有科室
    @Override
    public Result queryOffice() {
        return officeAPI.queryOffice(new QueryOfficeParam());
    }

    //查询医生详情
    @Override
    public Result queryDoctor(Integer doctorId) {
        QueryStaffParam queryStaffParam = new QueryStaffParam();
        QueryCriteriaStaffParam queryCriteriaStaffParam = new QueryCriteriaStaffParam();
        queryCriteriaStaffParam.setStaffId(doctorId);
        queryStaffParam.setQueryCriteriaStaffParam(queryCriteriaStaffParam);
        return staffAPI.queryStaff(queryStaffParam);
    }

    //点击时间段预约
    @Override
    public Result register(RegisterParam registerParam) {
        String key = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getHeader("key");
        System.out.println("key======="+key);
        HisPatientDto patientDto = patientQueryApi.redisKey(key).getData();
        RLock rLock = redissonClient.getLock("register");
        boolean tryLock  = rLock.tryLock();
        Result<ChangeSchedulingDto> changeSchedulingDtoResult = null;
//        if (tryLock) {

            QuerySchedulingParam querySchedulingParam = new QuerySchedulingParam();
            QueryCriteriaSchedulingParam queryCriteriaSchedulingParam = new QueryCriteriaSchedulingParam();
            queryCriteriaSchedulingParam.setSchedulingId(registerParam.getSchedulingId());
            querySchedulingParam.setQueryCriteriaSchedulingParam(queryCriteriaSchedulingParam);
            SchedulingDto schedulingDto = schedulingAPI.queryScheduling(querySchedulingParam).getData().getSchedulingDtoList().getList().get(0);

            AddHisRegisterParam addHisRegisterParam = new AddHisRegisterParam();
//            addHisRegisterParam.setRegisterSort(changeSchedulingDtoResult.getData().getSortPosition());
            addHisRegisterParam.setRegisterTime(registerParam.getRegisterTime());
            BeanUtils.copyProperties(patientDto, addHisRegisterParam);
            BeanUtils.copyProperties(schedulingDto, addHisRegisterParam);
            //查询医生详情
            QueryStaffParam staffParam = new QueryStaffParam();
            QueryCriteriaStaffParam queryCriteriaStaffParam = new QueryCriteriaStaffParam();
            queryCriteriaStaffParam.setStaffId(registerParam.getStaffId());
            staffParam.setQueryCriteriaStaffParam(queryCriteriaStaffParam);
            StaffDto staffDto = staffAPI.queryStaff(staffParam).getData().getStaffDtoList().getList().get(0);
            //科室名字
            addHisRegisterParam.setOfficeName(registerParam.getOfficeName());
            //医生
            addHisRegisterParam.setDoctorId(staffDto.getStaffId());
            addHisRegisterParam.setDoctorName(staffDto.getStaffName());
            //挂号费
            addHisRegisterParam.setRegisterPrice(schedulingDto.getSchedulingPrice());
            //创建挂号
            Result<HisRegisterDto> registerDtoResult = registerQueryApi.newRegistration(addHisRegisterParam);
            //创建挂号失败
            if (registerDtoResult.getCode() != 200) {
                return registerDtoResult;
            }

            HisRegisterDto registerDto = registerDtoResult.getData();
            //创建成功，预约人数修改,更新挂号表
            SchedulingIdAndStaffIdParam staffIdParam = new SchedulingIdAndStaffIdParam();
            BeanUtils.copyProperties(registerParam, staffIdParam);
            changeSchedulingDtoResult = schedulingAPI.changeAppointmentNumber(staffIdParam);
            ModifyHisRegisterParam modifyHisRegisterParam = new ModifyHisRegisterParam();
            modifyHisRegisterParam.setRegisterId(registerDto.getRegisterId());
            modifyHisRegisterParam.setRegisterSort(changeSchedulingDtoResult.getData().getSortPosition());
            Result<HisRegisterDto> hisRegisterDtoResult = registerQueryApi.modifyRegistration(modifyHisRegisterParam);


            //创建流水表
            CreateParam createParam = new CreateParam();
            createParam.setFlowingWaterType(0);
            createParam.setFlowingWaterPay(0);
            createParam.setPatientCardId(patientDto.getPatientCardid());
            createParam.setFlowingWaterMoney(schedulingDto.getSchedulingPrice());
            BeanUtils.copyProperties(registerDtoResult.getData(), createParam);
            Result<PayDto> payDtoResult = payApi.createPay(createParam);
            //创建流水失败

            SchedulingIdAndPayIdParam param = new SchedulingIdAndPayIdParam();
            param.setFlowingWaterId(payDtoResult.getData().getFlowingWaterId());
            param.setSchedulingId(schedulingDto.getSchedulingId());

            //30分钟时限
            rabbitTemplate.convertAndSend(AppConfig.EXCHANGE_NAME, AppConfig.RK_NAME, param, new MessagePostProcessor() {
                @Override
                public Message postProcessMessage(Message message) throws AmqpException {
                    message.getMessageProperties().setDeliveryMode(MessageDeliveryMode.PERSISTENT);
                    message.getMessageProperties().setExpiration(15*60*1000+"");
                    return message;
                }
            });
//        }else {
//            throw new OutpatientException(1900, "排队中");
//        }
//        rLock.unlock();
        return changeSchedulingDtoResult;
    }

    //支付挂号费
    @Override
    public Result payment(Integer registerId) {
        String key = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getHeader("key");
        Result<HisPatientDto> hisPatientDtoResult = patientQueryApi.redisKey(key);

        Result settlementPay = null;
        try {
            settlementPay = payApi.settlementPay(hisPatientDtoResult.getData().getPatientCardid());
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        return settlementPay;
    }

    //挂号支付回调
    @Override
    public Result paymentCallback(String patientCardid) {
        //查询用户id
        ListHisPatientParam listHisPatientParam = new ListHisPatientParam();
        listHisPatientParam.setPatientCardid(patientCardid);
        HisPatientDto patientDto = patientQueryApi.queryPatientInformation(listHisPatientParam).getData().getList().get(0);

        //查询病历
        ListHisCaseParam listHisCaseParam = new ListHisCaseParam();
        listHisCaseParam.setPatientId(patientDto.getPatientId());
        HisCaseDto caseDto = caseQueryApi.queryMedicalRecords(listHisCaseParam).getData().getList().get(0);

        ModifyHisPrescriptionParam modifyHisPrescriptionParam = new ModifyHisPrescriptionParam();
        prescriptionQueryApi.modifyMedication(modifyHisPrescriptionParam);
        return null;
    }

    //叫号查询患者队列
    @Override
    public Result queryPatientCohort() {
        String key = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getHeader("key");
        StaffDto staffDto = staffAPI.getStaff(key);
        return registerQueryApi.getAllRegist(staffDto.getOfficeId(), staffDto.getStaffId());
    }

    //叫号
    @Override
    public Result callNumber() {
        String key = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getHeader("key");
        StaffDto staffDto = staffAPI.getStaff(key);
        return registerQueryApi.callRegiest(staffDto.getOfficeId(), staffDto.getStaffId());
    }

    //过号
    @Override
    public Result skipPatient() {
        String key = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getHeader("key");
        StaffDto staffDto = staffAPI.getStaff(key);
        return registerQueryApi.crossSign(staffDto.getOfficeId(), staffDto.getStaffId());
    }

    //显示屏查询
    @Override
    public Result queryOfficePatientCohort(Integer officeId) {
        QueryStaffParam officeParam = new QueryStaffParam();
        QueryCriteriaStaffParam criteriaStaffParam = new QueryCriteriaStaffParam();
        criteriaStaffParam.setOfficeId(officeId);
        officeParam.setQueryCriteriaStaffParam(criteriaStaffParam);

        Map<String, List<HisRegisterDto>> map = new HashMap<>();

        //获取科室下的所有医生
        List<StaffDto> staffDtoList = staffAPI.queryStaff(officeParam).getData().getStaffDtoList().getList();
        for (StaffDto staffDto : staffDtoList) {
            List<HisRegisterDto> registerDtoList = registerQueryApi.getAllRegist(staffDto.getOfficeId(), staffDto.getStaffId()).getData();
            map.put(staffDto.getStaffName() + "_" + staffDto.getStaffId(), registerDtoList);
        }

        return Result.bulid(Map.class).setData(map);
    }

    //病历查询
    @Override
    public Result queryMedicalRecord(QueryMedicalRecordParam param) {

        //查询患者表，获取id
        ListHisPatientParam listHisPatientParam = new ListHisPatientParam();
        listHisPatientParam.setPatientName(param.getPatientName());
//        listHisPatientParam.
        Result<PageDTO<HisPatientDto>> pageDTOResult = patientQueryApi.queryPatientInformation(listHisPatientParam);

        //查询病历
        ListHisCaseParam caseParam = new ListHisCaseParam();
        caseParam.setPageParam(param.getPageParam());
        List<HisPatientDto> list = pageDTOResult.getData().getList();
        caseParam.setPatientId(list.get(0).getPatientId());

        return caseQueryApi.queryMedicalRecords(caseParam);
    }

    //生成病历
    @Override
    public Result generateMedicalRecord(GenerateMedicalRecordParam param) {

        //根据id查询挂号信息
        ListHisRegisterParam listHisRegisterParam = new ListHisRegisterParam();
        listHisRegisterParam.setRegisterId(param.getRegisterId());
        Result<PageDTO<HisRegisterDto>> registerMessage = registerQueryApi.registerMessage(listHisRegisterParam);
        HisRegisterDto registerDto = registerMessage.getData().getList().get(0);

        //根据id查询患者信息
        ListHisPatientParam listHisPatientParam = new ListHisPatientParam();
        listHisPatientParam.setPatientId(registerDto.getPatientId());
        Result<PageDTO<HisPatientDto>> pageDTOResult = patientQueryApi.queryPatientInformation(listHisPatientParam);
        HisPatientDto hisPatientDto = pageDTOResult.getData().getList().get(0);

        //生成病历
        AddHisCaseParam caseParam = new AddHisCaseParam();
        BeanUtils.copyProperties(registerDto, caseParam);
        BeanUtils.copyProperties(param, caseParam);
        BeanUtils.copyProperties(hisPatientDto, caseParam);

        return caseQueryApi.generateMedicalRecords(caseParam);
    }

    //查看病历
    @Override
    public Result viewMedicalRecord(Integer caseId) {
        ListHisCaseParam hisCaseParam = new ListHisCaseParam();
        hisCaseParam.setCaseId(caseId);

        return caseQueryApi.queryMedicalRecords(hisCaseParam);
    }

    //查看检查价格项目
    @Override
    public Result viewInspectionItems() {
        return checkPriceAPI.queryCheckPrice(new QueryCheckPriceParam());
    }

    //生成检查单
    @Override
    public Result generateChecklist(GenerateChecklistParam param) {

        //查询检查价格项目
        QueryCheckPriceParam priceParam = new QueryCheckPriceParam();
        QueryCriteriaParam criteriaParam = new QueryCriteriaParam();
        ArrayList<CheckPriceDto> list = new ArrayList<>();

        for (Integer id : param.getCheckPriceIds()) {
            criteriaParam.setCheckPriceId(id);
            priceParam.setQueryCriteriaParam(criteriaParam);
            Result<CheckPriceListDto> dtoResult = checkPriceAPI.queryCheckPrice(priceParam);
            list.add(dtoResult.getData().getPageDto().getList().get(0));
        }

        CreateOrModifyCheckParam checkParam = new CreateOrModifyCheckParam();
        List<CheckParam> checkParamList = CopyBeanUtil.copyBean(list, CheckParam.class);

        //查询患者信息
        ListHisPatientParam hisPatientParam = new ListHisPatientParam();
        hisPatientParam.setPatientId(param.getPatientId());
        HisPatientDto patientDto = patientQueryApi.queryPatientInformation(hisPatientParam).getData().getList().get(0);

        for (CheckParam c : checkParamList) {
            c.setPatientId(param.getPatientId());
            c.setPatientName(param.getPatientName());
            c.setCaseId(param.getCaseId());

            //创建流水表
            CreateParam createParam = new CreateParam();
            createParam.setFlowingWaterType(1);
            createParam.setFlowingWaterPay(0);
            createParam.setPatientId(patientDto.getPatientId());
            createParam.setPatientName(patientDto.getPatientName());
            createParam.setPatientCardId(patientDto.getPatientCardid());
            createParam.setFlowingWaterMoney(c.getCheckPricePrice());
            payApi.createPay(createParam);
        }
        checkParam.setCheckParamList(checkParamList);


        return checkAPI.createOrModifyCheck(checkParam);
    }

    //查看检查结果
    @Override
    public ViewInspectionResultsDto viewInspectionResults(ViewInspectionResultsParam param) {

        ViewInspectionResultsDto dto = new ViewInspectionResultsDto();
        List<Object> list = new ArrayList<>();

        //查询三个表
        QueryBloodParam bloodParam = new QueryBloodParam();
        BeanUtils.copyProperties(param, bloodParam);
        Result<QueryBloodDto> bloodDtoResult = bloodAPI.queryBlood(bloodParam);
        list.add(bloodDtoResult.getData());

        QueryUroscopyParam queryUroscopyParam = new QueryUroscopyParam();
        BeanUtils.copyProperties(param, queryUroscopyParam);
        Result<QueryUroscopyDto> uroscopyDtoResult = uroscopyAPI.queryUroscopy(queryUroscopyParam);
        list.add(uroscopyDtoResult.getData());

        QueryImageParam queryImageParam = new QueryImageParam();
        BeanUtils.copyProperties(param, queryImageParam);
        Result<QueryImageDto> imageDtoResult = imageAPI.queryImage(queryImageParam);
        list.add(imageDtoResult.getData());

        dto.setInspectionResultList(list);
        return dto;
    }

    //根据名称查询药品
    @Override
    public Result queryMedicineName(String medicineName) {
        return null;
    }

    //生成或修改药品单
    @Override
    public Result generateDrugOrder(GenerateDrugOrderParam param) {
        //删除原有用药单
        DeleteMedicationParam deleteMedicationParam = new DeleteMedicationParam();
        BeanUtils.copyProperties(param, deleteMedicationParam);
        prescriptionQueryApi.deleteByIdMedication(deleteMedicationParam);

        //查询患者信息
        ListHisPatientParam hisPatientParam = new ListHisPatientParam();
        hisPatientParam.setPatientId(param.getPatientId());

        //新增
        AddByIdHisPrescriptionParam add = new AddByIdHisPrescriptionParam();
        List<AddHisPrescriptionParam> list = CopyBeanUtil.copyBean(param.getPrescriptionList(), AddHisPrescriptionParam.class);

        HisPatientDto patientDto = patientQueryApi.queryPatientInformation(hisPatientParam).getData().getList().get(0);
        DrugsDto drugsDto = null;
        for (AddHisPrescriptionParam prescriptionParam : list) {
            drugsDto = drugsApi.getDrugsById(prescriptionParam.getMedicineId()).getData();
            BigDecimal price = new BigDecimal(drugsDto.getMedicineRetailPrice());
            prescriptionParam.setPrescriptionPrice(price);

            //创建流水表
            CreateParam createParam = new CreateParam();
            createParam.setFlowingWaterType(0);
            createParam.setFlowingWaterPay(0);
            createParam.setPatientId(patientDto.getPatientId());
            createParam.setPatientName(patientDto.getPatientName());
            createParam.setPatientCardId(patientDto.getPatientCardid());
            BigDecimal num = new BigDecimal(prescriptionParam.getPrescriptionNum());
            createParam.setFlowingWaterMoney(price.multiply(num));
            payApi.createPay(createParam);
        }
        add.setList(list);
        add.setCareId(param.getCareId());
        add.setOrderFormId(param.getOrderFormId());

        return prescriptionQueryApi.newDrugs(add);
    }

    //查询药品单
    @Override
    public Result queryDrugOrder(Integer careId) {
        ListHisPrescriptionParam prescriptionParam = new ListHisPrescriptionParam();
        prescriptionParam.setCareId(careId);
        return prescriptionQueryApi.queryMedication(prescriptionParam);
    }

//    //药品单收费
//    @Override
//    public Result tollDrugOrder(Integer careId) {
////        Result settlementPay = null;
////        try {
////            settlementPay = payApi.settlementPay(hisPatientDtoResult.getData().getPatientCardid());
////        } catch (AlipayApiException e) {
////            e.printStackTrace();
////        }
//        return null;
//    }

    //药品单收费回调
    @Override
    public Result tollDrugOrderCallback() {
        return null;
    }

    //取药
    @Override
    public Result takeMedicine(Integer careId) {
        //查询用药单
        ListHisPrescriptionParam listHisPrescriptionParam = new ListHisPrescriptionParam();
        listHisPrescriptionParam.setCareId(careId);
        Result<PageDTO<HisPrescriptionDto>> medication = prescriptionQueryApi.queryMedication(listHisPrescriptionParam);
        List<HisPrescriptionDto> list = medication.getData().getList();

        //修改库存
        StockParam stockParam = new StockParam();
        for (HisPrescriptionDto prescriptionDto : list) {
            Result<DrugsDto> stockResult = stockApi.getStock(prescriptionDto.getMedicineId());
            BeanUtils.copyProperties(stockResult, stockParam);
            stockParam.setStockSurplus(stockParam.getStockSurplus() - prescriptionDto.getPrescriptionNum());

            stockApi.updateStock(stockParam);
        }

        //修改用药单领药状态
        ModifyHisPrescriptionParam prescriptionParam = new ModifyHisPrescriptionParam();
        prescriptionParam.setCareId(careId);

        return prescriptionQueryApi.receivingMedicine(prescriptionParam);
    }

    //住院申请单
    @Override
    public Result applyForHospitalization(PatientDetailsParam param) {
        if (ObjectUtil.isNull(param.getRegisterId())) {
            throw new DIYException(999, "缺少挂号id");
        }
        //补充患者信息
        ModifyHisPatientParam modifyHisPatientParam = new ModifyHisPatientParam();
        BeanUtils.copyProperties(param, modifyHisPatientParam);
        Result<HisPatientDto> patientDtoResult = patientQueryApi.modifyPatientInformation(modifyHisPatientParam);

        //根据id查询挂号信息
        ListHisRegisterParam hisRegisterParam = new ListHisRegisterParam();
        hisRegisterParam.setRegisterId(param.getRegisterId());
        HisRegisterDto registerDto = registerQueryApi.registerMessage(hisRegisterParam).getData().getList().get(0);

        //患者住院
        HisHospitalRecordsAddParam recordsAddParam = new HisHospitalRecordsAddParam();
        BeanUtils.copyProperties(patientDtoResult.getData(), recordsAddParam);
        BeanUtils.copyProperties(registerDto, recordsAddParam);
        return hospitalRecordsApi.addHisHospitalRecords(recordsAddParam);
    }

    //查询当前科室值班医生
    @Override
    public Result querySchedulingInfo(QueryDoctorParam param) {
        IdAndTimeParam idAndTimeParam = CopyBeanUtil.copyBean(param, IdAndTimeParam.class);
        return schedulingAPI.querySchedulingInfo(idAndTimeParam);
    }


}
